home *** CD-ROM | disk | FTP | other *** search
/ L' Effet Pommier 3 / L'Effet Pommier - Volume 03.iso / Programmation / gray image 2.1 / write_xwd.cc < prev    next >
Text File  |  1995-05-30  |  7KB  |  271 lines

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /*
  3.  ************************************************************************
  4.  *
  5.  *               Grayscale Image
  6.  *
  7.  *    Write the image into the file in the X11 Window dump format
  8.  *             and display it with xwud program
  9.  *
  10.  * $Id: write_xwd.cc,v 2.0 1995/03/09 15:24:11 oleg Exp oleg $
  11.  *
  12.  ************************************************************************
  13.  */
  14.  
  15. #include "image.h"
  16. #include "endian_io.h"
  17. #ifdef __GNUC__
  18. #pragma implementation "x11wd.h"
  19. #endif
  20. #include "x11wd.h"
  21.  
  22.  
  23. /*
  24.  *------------------------------------------------------------------------
  25.  *        Writing of X11 WD data structures
  26.  */
  27.  
  28. void X11XColor::write(EndianOut& outs) const
  29. {
  30.   outs.write_long ( pixel );
  31.   outs.write_short( red );
  32.   outs.write_short( green );
  33.   outs.write_short( blue );
  34.   outs.write_byte ( flags );
  35.   outs.write_byte ( pad );
  36. }
  37.  
  38. void X11XColor::write_gray_colormap(EndianOut& outs, const int ncolors)
  39. {
  40.   for(register int i = 0; i < ncolors; i++)
  41.   {
  42.     X11XColor grayshade(i, ncolors == 256 ? ((long)i<<8) | i :
  43.                (((long)i<<16)-i)/(ncolors-1) );
  44.     grayshade.write(outs);
  45.   }
  46. }
  47.  
  48. /*
  49.  *------------------------------------------------------------------------
  50.  *               Class XWdump
  51.  *     designed to contain the control info about the image
  52.  *        as defined in the X Window Dump file 
  53.  */
  54.  
  55. class XWdump        // All the info pertaining to the XWD file
  56.    : public X11WDFileHeader, public EndianOut {
  57.  
  58. private:
  59.      const IMAGE& image;        // Image being processed
  60.      const char * title;        // Title for the image in the file
  61.  
  62.      void write_image_data(void);
  63.  
  64. public:
  65.      XWdump(const IMAGE& _image);            // Constructor
  66.      void set_title(const char * user_title);
  67.      void write_image(const char * file_name);
  68. };
  69.  
  70. /*
  71.  *------------------------------------------------------------------------
  72.  *            Construct the XWdump
  73.  *       by filling out the fields of the structure from the IMAGE 
  74.  */
  75.  
  76. XWdump::XWdump(const IMAGE& _image) : image(_image)
  77. {
  78.   title  = image.q_name();
  79.   assure(image.q_depth() <= 8,
  80.      "Sorry, the program cannot write images with depth > 8");
  81.  
  82.   header_size = sizeof(X11WDFileHeader) + strlen(title) + 1;
  83.   file_version = X11WD_FILE_VERSION;
  84.   pixmap_format = ZPixmap;
  85.   pixmap_width = image.q_ncols();
  86.   pixmap_height = image.q_nrows();
  87.   xoffset = 0;
  88.   xbyte_order = MSBFirst; set_bigendian();
  89.   bitmap_bit_order = MSBFirst;
  90.   window_width = image.q_ncols();
  91.   window_height = image.q_nrows();
  92.   window_x = 0;
  93.   window_y = 0;
  94.   window_bdrwidth = 0;
  95.  
  96.   pixmap_depth = 8;
  97.   bits_per_pixel = 8;
  98.   colormap_entries = 256;
  99.   ncolors = 256;
  100.   bytes_per_line = image.q_ncols();
  101.   
  102.   bitmap_unit = 8;
  103.   bitmap_pad = 8;
  104.   visual_class = StaticGray;
  105.   red_mask = 0;
  106.   green_mask = 0;
  107.   blue_mask = 0;
  108.  
  109.   bits_per_rgb = pixmap_depth;
  110. }
  111.  
  112. /*
  113.  *------------------------------------------------------------------------
  114.  *            Set up the title for the image
  115.  * image.name == "" && user title == ""  ---> resulting title = ""
  116.  * image.name != "" && user title == ""  ---> resulting title = image.name
  117.  * image.name == "" && user title != ""  ---> resulting title = user title
  118.  * image.name != "" && user title != ""  ---> 
  119.  *            resulting title = "image name/user title"
  120.  *
  121.  * Note that XWdump::title has been already set to image.title.
  122.  * If it is changed, the XWdump::header_size should be modified as well
  123.  */
  124.  
  125. void XWdump::set_title(const char * user_title)
  126. {
  127.   if( strlen(user_title) == 0 )
  128.     return;
  129.  
  130.   register int old_title_len = strlen(title);
  131.  
  132.   if( strlen(title) == 0 )        // No image title
  133.     title = user_title;
  134.   else
  135.     title = 
  136.      strcat(
  137.       strcat(
  138.        strcpy((char *)calloc(strlen(title)+1+strlen(user_title)+1,
  139.                  sizeof(char)),title),
  140.        "/"),
  141.       user_title);
  142.  
  143.   header_size += strlen(title) - old_title_len;
  144. }
  145.  
  146. /*
  147.  *------------------------------------------------------------------------
  148.  *            Writing the X window dump file
  149.  */
  150.  
  151. void XWdump::write_image(const char * file_name)
  152. {
  153.  
  154.   open(file_name);
  155.                       // Writing the header
  156.   write_long( header_size );
  157.   write_long( file_version );
  158.   write_long( pixmap_format );
  159.   write_long( pixmap_depth );
  160.   write_long( pixmap_width );
  161.   write_long( pixmap_height );
  162.   write_long( xoffset );
  163.   write_long( xbyte_order );
  164.   write_long( bitmap_unit );
  165.   write_long( bitmap_bit_order );
  166.   write_long( bitmap_pad );
  167.   write_long( bits_per_pixel );
  168.   write_long( bytes_per_line );
  169.   write_long( visual_class );
  170.   write_long( red_mask );
  171.   write_long( green_mask );
  172.   write_long( blue_mask );
  173.   write_long( bits_per_rgb );
  174.   write_long( colormap_entries );
  175.   write_long( ncolors );
  176.   write_long( window_width );
  177.   write_long( window_height );
  178.   write_long( window_x );
  179.   write_long( window_y );
  180.   write_long( window_bdrwidth );
  181.   
  182.   write(title, strlen(title)+1);    // Write out the dump name
  183.   X11XColor::write_gray_colormap(*this,ncolors);
  184.   write_image_data();
  185.   
  186.   close();
  187. }
  188.  
  189. /*
  190.  *------------------------------------------------------------------------
  191.  *            Write out the pixel matrix 
  192.  *          with 'bits_per_pixel'representation
  193.  */
  194.  
  195. void XWdump::write_image_data(void)
  196. {
  197.   register card row, col;
  198.   const long int maxval = (1 << image.q_depth()) - 1;
  199.   const long int bigger_maxval = (1 << bits_per_pixel) - 1;
  200.  
  201.   assure(maxval <= bigger_maxval, 
  202.      "Cannot display image with too many bits per pixel");
  203.  
  204.                 // Using simplified procedure if possible
  205.   if( bits_per_pixel == 8 && image.q_depth() == 8 )
  206.   {
  207.     for( row = 0; row < pixmap_height; ++row )
  208.       for( col = 0; col < pixmap_width; ++col )
  209.     write_byte( image(row,col) );
  210.     return;
  211.   }
  212.  
  213.                 // Handle the general case if tricks don't
  214.                 // work
  215.   for( row = 0; row < pixmap_height; ++row )
  216.   {
  217.     register  int  bitshift = 8 - bits_per_pixel;
  218.     register char byte = 0;
  219.  
  220.     for( col = 0; col < pixmap_width; ++col )
  221.     {
  222.       register long s = image(row,col);
  223.       
  224.       if( maxval != bigger_maxval )
  225.     s = (((long)s << bits_per_pixel)-s) / maxval;
  226.       byte |= s << bitshift;
  227.       bitshift -= bits_per_pixel;
  228.       if( bitshift < 0 )
  229.       {
  230.      write_byte( byte );
  231.      bitshift = 8 - bits_per_pixel;
  232.      byte = 0;
  233.       }
  234.       if( bitshift < 8 - (signed)bits_per_pixel )
  235.     write_byte( byte );
  236.     }
  237.   }
  238. }
  239.  
  240.  
  241. /*
  242.  *------------------------------------------------------------------------
  243.  *                   Root modules 
  244.  *        for writing the image and displaying it
  245.  */
  246.  
  247. void IMAGE::write_xwd(const char * file_name,const char * title) const
  248. {
  249.   is_valid();
  250.  
  251.   message("\nPreparing XWD file with name '%s'\n",file_name);
  252.   XWdump XWdump(*this);
  253.   XWdump.set_title(title);
  254.   XWdump.write_image(file_name);
  255. }
  256.  
  257. #ifndef __MWERKS__
  258.                 // Display the image with 'xwud' program
  259. void IMAGE::display(const char * title) const
  260. {
  261.   register int kid_id;            // ID of the kid process
  262.   if( getenv("DISPLAY") == (char *)0 )    // Bypass if isn't an X terminal
  263.     return;
  264.   assert( (kid_id = fork()) != -1 );
  265.   if( kid_id == 0 )            // We're in the kid process
  266.   {
  267.     write_xwd("| xwud",title);
  268.     exit(0);
  269.   }
  270. }
  271. #endif